package org.wheel.plugins.toolkit.sql.core;

import org.wheel.plugins.toolkit.sql.entity.BeanMeta;
import org.wheel.plugins.toolkit.sql.function.F;
import org.wheel.plugins.toolkit.sql.function.FunctionBuilder;
import org.wheel.plugins.toolkit.sql.helper.ColumnRef;
import org.wheel.plugins.toolkit.sql.helper.FieldMeta;
import org.wheel.plugins.toolkit.sql.helper.SFunction;
import org.wheel.plugins.toolkit.sql.render.UpdateSqlRenderer;
import org.wheel.plugins.toolkit.util.ReflectUtil;

/**
 * 链式 UPDATE 构造器 – 极简版
 * 所有 SET 数据转交给 UpdateSqlRenderer 内部维护，本类只做入口校验。
 */
public class LambdaUpdateWrapper<T> extends AbstractWrapper<T, LambdaUpdateWrapper<T>> {

    /* 渲染器内部持有 SetBuilder，LambdaUpdateWrapper 本身无 Map 缓存 */
    private final UpdateSqlRenderer renderer;

    public LambdaUpdateWrapper(Class<T> clazz) {
        this(clazz, null);
    }

    public LambdaUpdateWrapper(Class<T> clazz, String tableAlias) {
        super(clazz, tableAlias);
        this.renderer = new UpdateSqlRenderer(dialect);
    }

    /* ===================== SET 入口 ===================== */
    public <T> LambdaUpdateWrapper<T> update(T bean) {
        return update(bean, true);
    }

    public <T> LambdaUpdateWrapper<T> update(T bean, boolean ignoreNull) {
        BeanMeta beanMeta = BeanMeta.of(clazz);
        for (FieldMeta fieldMeta : beanMeta.getFields()) {
            // 主键不参与 SET
            if(fieldMeta.isPrimaryKey()){
                continue;
            }
            Object val = ReflectUtil.getFieldValue(bean, fieldMeta.getFieldName());
            if(ignoreNull && val == null){
                continue;
            }
            renderer.addColumnValue(ColumnRef.of(this.mainTableAlias, fieldMeta.getColumn(), null)
                            .withoutAlias().withWrapper(this),
                    ReflectUtil.invokeGetter(bean, fieldMeta.getFieldName()), this);
        }

        return (LambdaUpdateWrapper<T>)this;
    }

    public <R> LambdaUpdateWrapper<T> set(SFunction<T, R> column, R value) {
        renderer.addColumnValue(ColumnRef.of(column, this).withoutAlias(), value, this);
        return this;
    }

    public <R> LambdaUpdateWrapper<T> set(String column, R value) {
        renderer.addColumnValue(F.col(column), value, this);
        return this;
    }

    public <R> LambdaUpdateWrapper<T> setSql(SFunction<T, R> column, String rawSql) {
        renderer.addColumnSql(ColumnRef.of(column, this).withoutAlias(), rawSql);
        return this;
    }

    public LambdaUpdateWrapper<T> setSql(String... rawSqls) {
        for (String sql : rawSqls) renderer.addRawSql(sql);
        return this;
    }

    /* ===================== 禁用无关 API ===================== */
    @Override
    public LambdaUpdateWrapper<T> function(FunctionBuilder fn) {
        throw new UnsupportedOperationException("UPDATE 不支持 SELECT 函数");
    }

    /* ===================== SQL 出口 ===================== */
    @Override
    public String getSql() {
        String sql = renderer.render(tree, getContext().getParamBank());
        return renderSql(sql);
    }
}
